package com.changzhi.controller;

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.changzhi.common.exception.ServiceException;
import com.changzhi.common.util.Result;
import com.changzhi.ldyl.model.QQUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.Map;

/**
 * qq登录
 */
@Slf4j
@CrossOrigin
@RequestMapping("qq")
@RestController
public class QQController {

	@Value("${constants.qqAppId}")
	private String qqAppId;

	@Value("${constants.qqAppSecret}")
	private String qqAppSecret;

	@Value("${constants.qqRedirectUrl}")
	private String qqRedirectUrl;

	@Value("${h5.domain}")
	private String h5Domain;

	/**
	 * 获得跳转到qq登录页的url,前台直接a连接访问
	 * @return
	 */
	@GetMapping("/getQqCode")
	public void getCode(HttpServletResponse response) throws Exception {
		// 拼接url
		StringBuilder sb = new StringBuilder();
		sb.append("https://graph.qq.com/oauth2.0/authorize?response_type=code&state=ok");
		sb.append("&client_id=" + qqAppId);
		sb.append("&redirect_uri=" + URLEncoder.encode(qqRedirectUrl));//回调地址要进行Encode转码
		response.sendRedirect(sb.toString());
	}

	
	/**
	 * 开始登录
	 * 
	 * @param code
	 * @param 
	 * //实际业务 ：token过期调用刷新    token重新获取token信息
	 * 数据库字段: accessToken，expiresIn，refreshToken，openId
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/callback")
	public void qqLogin(String code, HttpServletResponse response) throws Exception {
		log.info("methodName:qqLogin, code={}", code);
	    //获取accessToken
		String accessToken = getToken(code);
		//获取openId
	    String openId = getOpenId(accessToken);
	    //tocket过期刷新token
	    //Map<String, Object> refreshToken = refreshToken(qqProperties);
		//重定向
		StringBuilder url = new StringBuilder();
		url.append(h5Domain + "/#/login?identityType=QQ");
		url.append("&accessToken=" + accessToken);
		url.append("&openId=" + openId);
		response.sendRedirect(url.toString());
	}

	@RequestMapping("/qqUserInfo")
	public Result UserInfo(@RequestBody Map<String,Object> params) throws Exception {
		log.info("methodName:userInfo, params={}", JSON.toJSONString(params));
		// 取token
		String accessToken = (String) params.get("accessToken");
		String openId = (String) params.get("openId");
		if (!StringUtils.isNotEmpty(accessToken) || !StringUtils.isNotEmpty(openId)) {
			throw new ServiceException("参数缺失");
		}
		//获取unionId
		String unionId = getUnionId(accessToken);
		//获取用户数据
		QQUserInfo userInfo = getUserInfo(accessToken, openId);
		userInfo.setUnionid(unionId);
		log.warn("methodName:userInfo, userInfo={}", JSON.toJSONString(userInfo));
		return Result.success(userInfo);
	}

	/**
	 * 获得token信息（授权，每个用户的都不一致） --> 获得token信息该步骤返回的token期限为一个月
	 */
	private String getToken(String code){
		StringBuilder url = new StringBuilder();
		url.append("https://graph.qq.com/oauth2.0/token?grant_type=authorization_code");
		url.append("&client_id=" + qqAppId);
		url.append("&client_secret=" + qqAppSecret);
		url.append("&code=" + code);
		url.append("&redirect_uri=" + URLEncoder.encode(qqRedirectUrl));
		// 获得token
		HttpRequest request = HttpRequest.get(url.toString());
		String result = request.execute().body();
		log.info("getToken().result={}" , url.toString());
		// 把token保存
		String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(result, "&");
		String accessToken = StringUtils.substringAfterLast(items[0], "=");
	    //token信息
		return accessToken;
	}

	/**
	 * 刷新token 信息（token过期，重新授权）
	 * 
	 * @return
	 * @throws Exception
	 */
	@GetMapping("/refreshToken")
	public Map<String,Object> refreshToken(Map<String,Object> qqProperties){
		// 获取refreshToken
		String refreshToken = (String) qqProperties.get("refreshToken");
		StringBuilder url = new StringBuilder("https://graph.qq.com/oauth2.0/token?grant_type=refresh_token");
		url.append("&client_id=" + qqAppId);
		url.append("&client_secret=" + qqAppSecret);
		url.append("&refresh_token=" + refreshToken);
		HttpRequest request = HttpRequest.get(url.toString());
		String result = request.execute().body();
		log.info("refreshToken().result={}" + url.toString());
		// 把新获取的token存到map中
		String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(result, "&");
		String accessToken = StringUtils.substringAfterLast(items[0], "=");
		Long expiresIn = new Long(StringUtils.substringAfterLast(items[1], "="));
		String newRefreshToken = StringUtils.substringAfterLast(items[2], "=");
		//重置信息
		qqProperties.put("accessToken", accessToken);
		qqProperties.put("expiresIn", String.valueOf(expiresIn));
		qqProperties.put("refreshToken", newRefreshToken);
		return qqProperties;
	}

	/**
	 * 获取用户openId（根据token）
	 * @qqProperties 把openId存到map中
	 * @return
	 * @throws Exception
	 */
	public String getOpenId(String accessToken){
		// 获取保存的用户的token
		if (!StringUtils.isNotEmpty(accessToken)) {
			throw new ServiceException("未授权");
		}
		StringBuilder url = new StringBuilder("https://graph.qq.com/oauth2.0/me?");
		url.append("access_token=" + accessToken);
		HttpRequest request = HttpRequest.get(url.toString());
		String result = request.execute().body();
		log.info("getUserInfo().getOpenId=" + url.toString());
		String openId = StringUtils.substringBetween(result, "\"openid\":\"", "\"}");
		return openId;
	}

	/**
	 * 根据token,openId获取用户信息
	 */
	public QQUserInfo getUserInfo(String accessToken, String openId) throws Exception {
		//拼接url
		StringBuilder url = new StringBuilder("https://graph.qq.com/user/get_user_info?");
		url.append("access_token=" + accessToken);
		url.append("&oauth_consumer_key=" + qqAppId);
		url.append("&openid=" + openId);
		// 获取qq相关数据
		HttpRequest request = HttpRequest.get(url.toString());
		String result = request.execute().body();
		log.info("getUserInfo().result=" + url.toString());
		Object json = JSON.parseObject(result, QQUserInfo.class);
		QQUserInfo userInfo = (QQUserInfo) json;
		return userInfo;
	}

	/**
	 * 根据token,获取unionid
	 */
	public String getUnionId(String accessToken){
		if (!StringUtils.isNotEmpty(accessToken)) {
			throw new ServiceException("参数缺失");
		}
		//拼接url
		StringBuilder url = new StringBuilder("https://graph.qq.com/oauth2.0/me?unionid=1&fmt=json&");
		url.append("access_token=" + accessToken);
		// 获取qq相关数据
		HttpRequest request = HttpRequest.get(url.toString());
		String result = request.execute().body();
		log.info("getUserInfo().result=" + url.toString());
		QQUserInfo qqUserInfo = (QQUserInfo) JSON.parseObject(result, QQUserInfo.class);
		return qqUserInfo.getUnionid();
	}
}
